#include <stdio.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/spi/spidev.h>
#include <linux/spi/spi.h>
#include <strings.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>

#define SPI_DEVICE_PATH "/dev/spidev0.0"

typedef struct _spi_config
{
    /* data */
    int mode;
    int speed;
    int bits;
}spi_config;

static int spi_attr_config(int fd,spi_config *config)
{
    int ret;
    if (NULL == config)
        return -1;
    ret = ioctl(fd, SPI_IOC_WR_MODE, &config->mode);
    if (ret != 0)
    {
        perror("config spi write mode error \n");
        return ret;
    }
    ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &config->speed);
    if (ret != 0)
    {
        perror("config spi speed error \n");
        return ret;
    }

    ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &config->bits);
    if (ret != 0)
    {
        perror("config spi transfer bits error \n");
        return ret;
    }

    return 0;
}

int spi_open(char* device)
{
    int fd = -1;
    if (device!= NULL)
    {
        fd = open(device, O_RDWR);
        if (fd < 0)
        {
            printf("open spi device error\n");
            return -1;
        }
    }
    return fd;
}

int spi_read(int fd,unsigned char *data, int len)
{
    int ret;

    struct spi_ioc_transfer spi_data;
    memset(&spi_data, 0, sizeof(spi_data));
    spi_data.tx_buf = (unsigned long)NULL;
    spi_data.rx_buf = (unsigned long)data;
    spi_data.len = len;
    ret = ioctl(fd, SPI_IOC_MESSAGE(1), &spi_data);
    if (ret < 1)
    {
        printf("spi write error\n");
    }
    return 0;
}

int spi_write(int fd,unsigned char *data, int len)
{
    int ret;

    struct spi_ioc_transfer spi_data;
    memset(&spi_data, 0, sizeof(spi_data));
    spi_data.tx_buf = (unsigned long)data;
    spi_data.rx_buf = (unsigned long)NULL;
    spi_data.len = len;
    ret = ioctl(fd, SPI_IOC_MESSAGE(1), &spi_data);
    if (ret < 1)
    {
        printf("spi write error\n");
    }
    return 0;
}

int spi_write_read(int fd,unsigned char *txdata,unsigned char *rxdata, int len)
{
    struct spi_ioc_transfer spi ;

    memset (&spi, 0, sizeof (spi)) ;

    spi.tx_buf        = (unsigned long)txdata ;
    spi.rx_buf        = (unsigned long)rxdata ;
    spi.len           = len ;
    spi.delay_usecs   = 0 ;
    spi.bits_per_word = 8 ;

    return ioctl (fd, SPI_IOC_MESSAGE(1), &spi) ;
}



int main(int argc,char *argv[])
{
    spi_config config = {0};
    int fd = 0;
    int ret;
    unsigned short device_id;
    unsigned char write_buf[1024] = {1,2,3};
    unsigned char read_buf[1024] = {0};

    fd = spi_open(SPI_DEVICE_PATH);

    printf("spi open fd == %d\n",fd);
    config.mode = 0;
    config.bits = 8;
    config.speed = 1000000;
    spi_attr_config(fd,&config);

    W25Qxx_ReadManufactDeviceId(fd,&device_id);

    printf("\n");
    close(fd);
    return 0;
}
